package com.zkingsoft.actions.visitor;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileUploadException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.zkingsoft.constance.SystemConstance;
import com.zkingsoft.constraint.BaseController;
import com.zkingsoft.exception.GlobleException;
import com.zkingsoft.pojo.AjaxResult;
import com.zkingsoft.util.WebUtil;

/**
 * 
 * @Description: 不需要登录可以访问的action
 * @author:姜友瑶
 * @date 2016年8月31日
 */
@Controller
public class Home extends BaseController {

	@Value("${source_tomcat}")
	private String source_tomcat;

	@Value("${target_tomcat_home}")
	private String target_tomcat_home;

	@Value("${JAVA_HOME}")
	private String JAVA_HOME;

	private static Integer new_listen_port = new Integer(0);
	private static Integer new_shutdown_port = new Integer(0);

	/**
	 * 
	 * @Description: 首页配置
	 * @author:姜友瑶
	 * @return 返回类型 String
	 * @date 2016年8月28日
	 */
	@RequestMapping(value = "/")
	public String redirect() {
		return "redirect:/common/redirect/login";
	}

	/**
	 * 获取tomcatList
	 */
	@RequestMapping(value = "/getTomcatList")
	@ResponseBody
	public AjaxResult getTomcatList() {
		@SuppressWarnings("unchecked")
		Map<String, TomcatProperties> tomcatMap = (Map<String, TomcatProperties>) WebUtil
				.getServletContext().getAttribute(SystemConstance.TOMCATMAP);
		List<TomcatProperties> tomcatList = new ArrayList<>();
		for (String key : tomcatMap.keySet()) {
			tomcatList.add(tomcatMap.get(key));
		}
		Collections.sort(tomcatList, new Comparator<TomcatProperties>() {

			@Override
			public int compare(TomcatProperties o1, TomcatProperties o2) {

				return o1.getListen_port() - o2.getListen_port();
			}
		});
		return new AjaxResult(AjaxResult.STATUS_OK, tomcatList);
	}

	/**
	 * 获取单个tomcat信息
	 */
	@RequestMapping(value = "/getTomcat")
	@ResponseBody
	public AjaxResult getTomcat(String name) {
		@SuppressWarnings("unchecked")
		Map<String, TomcatProperties> tomcatMap = (Map<String, TomcatProperties>) WebUtil
				.getServletContext().getAttribute(SystemConstance.TOMCATMAP);
		TomcatProperties tomcat = tomcatMap.get(name);
		AjaxResult result = new AjaxResult(AjaxResult.STATUS_OK, "");
		result.putInMap("tomcat", tomcat);
		return result;
	}

	/**
	 * 创建tomcat
	 */
	@RequestMapping(value = "/addTomcat")
	@ResponseBody
	public AjaxResult addTomcat(String remark) {
		@SuppressWarnings("unchecked")
		Map<String, TomcatProperties> tomcatMap = (Map<String, TomcatProperties>) WebUtil
				.getServletContext().getAttribute(SystemConstance.TOMCATMAP);

		if (new_listen_port.equals(0)) {
			for (String key : tomcatMap.keySet()) {
				TomcatProperties tomcat = tomcatMap.get(key);

				new_listen_port = new_listen_port < tomcat.getListen_port() ? tomcat
						.getListen_port() : new_listen_port;
				new_shutdown_port = new_shutdown_port < tomcat
						.getShutdown_port() ? tomcat.getShutdown_port()
						: new_shutdown_port;
			}
		}
		new_listen_port++;
		new_shutdown_port++;

		String target_tomcat = target_tomcat_home + "tomcat-" + new_listen_port
				+ "/";// 目标路径
		File target_tomcat_dir = new File(target_tomcat);
		if (!target_tomcat_dir.isDirectory()) {
			target_tomcat_dir.mkdirs();
		}
		copyFile(source_tomcat, target_tomcat);
		editServerXml(target_tomcat + "conf/server.xml");
		
		//更新配置文件
		updateTomcatList(target_tomcat, remark);
		
		TomcatProperties tomcat = new TomcatProperties();
		tomcat.setName("tomcat-" + new_listen_port);
		tomcat.setPath(target_tomcat);
		tomcat.setRemark(remark);
		tomcat.setListen_port(new_listen_port);
		tomcat.setShutdown_port(new_shutdown_port);

		tomcatMap.put(tomcat.getName(), tomcat);
		WebUtil.getServletContext().setAttribute(SystemConstance.TOMCATMAP,
				tomcatMap);

		return new AjaxResult(AjaxResult.STATUS_OK, "创建成功");
	}

	/**
	 * 通用的图上传action 本方法目前只能支持单文件上传，如果需要多文件还要好好想想
	 * 
	 * @author jiangyouyao
	 */
	@RequestMapping(value = "/doUpload")
	public String doFileUpload(HttpServletResponse response,
			MultipartHttpServletRequest request) throws IOException,
			FileUploadException {
		// 文件保存目录路径
		String savePath = target_tomcat_home + request.getParameter("name")
				+ File.separator + "webapps";

		response.setContentType("text/html; charset=UTF-8");
		request.setCharacterEncoding("UTF-8");

		// 检查目录
		File uploadDir = new File(savePath);
		if (!uploadDir.isDirectory()) {
			uploadDir.mkdirs();
		}
		// 检查目录写权限
		if (!uploadDir.canWrite()) {
			request.setAttribute("status", "err");
			request.setAttribute("msg", "上传目录没有写权限");
		}
		Map<String, MultipartFile> fileMaps = request.getFileMap();
		for (String key : fileMaps.keySet()) {
			MultipartFile file = fileMaps.get(key);

			String fileName = file.getOriginalFilename();
			String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1)
					.toLowerCase();
			if (!"war".equals(fileExt)) {
				request.setAttribute("status", "err");
				request.setAttribute("msg", "上传文件扩展名是不允许的扩展名。<br>只允许.war文件格式。");
			}
			File uploadedFile = new File(savePath, fileName);
			try {
				FileCopyUtils.copy(file.getBytes(), uploadedFile);
			} catch (Exception e) {
				request.setAttribute("status", "err");
				request.setAttribute("msg", "上传文件失败 错误代码002");
			}
			request.setAttribute("status", "ok");
			request.setAttribute("msg", "上传文件成功");
		}

		return "common/info";
	}

	/**
	 * 执行tomcat命令
	 * 
	 * @throws IOException
	 */
	@RequestMapping(value = "/excute")
	@ResponseBody
	public AjaxResult excute(String order, String name) throws IOException {
		// StringBuilder cmdStr = new StringBuilder();
		Runtime rt = Runtime.getRuntime();

		String path = target_tomcat_home + name;

		switch (order) {
		case "startup":
			/*
			 * command -- 指定的系统命令。
			 * 
			 * envp --
			 * 字符串数组，其中每个元素的环境变量的设置格式为name=value，则返回null，如果子进程应该继承当前进程的环境.
			 * 
			 * dir -- 子进程的工作目录，或null，如果子进程应该继承当前进程的工作目录.
			 */
			if (System.getProperty("os.name").indexOf("Windows") != -1) {
				String[] envp = { // 环境变量设置
				"JAVA_HOME=" + JAVA_HOME, "CATALINA_HOME=" + path // Tomcat
				};
				rt.exec(path + "\\bin\\startup.bat", envp, new File(path));
			} else {
				rt.exec(new String[] { "sh", "-c", "" });
			}
			return new AjaxResult(AjaxResult.STATUS_OK, "启动成功");
		case "shutdown":

			if (System.getProperty("os.name").indexOf("Windows") != -1) {
				String[] envp = { // 环境变量设置
				"JAVA_HOME=" + JAVA_HOME, "CATALINA_HOME=" + path // Tomcat
				};
				rt.exec(path + "\\bin\\shutdown.bat", envp, new File(path));
			} else {
				rt.exec(new String[] { "sh", "-c", "" });
			}
			return new AjaxResult(AjaxResult.STATUS_OK, "关闭成功");
		case "clear":
			File webapps = new File(path + File.separator + "webapps");
			deleteFile(webapps);
			return new AjaxResult(AjaxResult.STATUS_OK, "清除成功");
		}
		return new AjaxResult(AjaxResult.STATUS_ERR, "执行失败，命令错误");
	}

	private void copyFile(String sourcePath, String targetPath) {
		File sourceFile = new File(sourcePath);
		if (sourceFile.isDirectory()) {
			File[] listFiles = sourceFile.listFiles();
			for (File file : listFiles) {
				copyFile(file.getPath(), targetPath);
			}
		} else {
			fileCopy(sourceFile, targetPath);
		}
	}

	private void fileCopy(File srcFile, String targetPath) {
		String srcPath = srcFile.getPath();

		String des = targetPath
				+ srcPath.substring(source_tomcat.length(), srcPath.length());
		createFile(des);

		FileChannel in = null;
		FileChannel out = null;
		try {
			in = new FileInputStream(srcPath).getChannel();
			out = new FileOutputStream(des).getChannel();
			in.transferTo(0, in.size(), out);// 连接两个通道，并且从in通道读取，然后写入out通道
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 创建一个文件
	 * 
	 * @param path
	 * @throws Exception
	 */
	private void createFile(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {// 判断文件是否存在
			System.out.println("目标文件已存在" + filePath);
			// msgArea.setText(msgArea.getText() + "\r\n" +"目标文件已存在" +
			// filePath);
		}
		if (file.isDirectory()) {// 判断文件是否为目录
			System.out.println("目标文件不能为目录！");
			// msgArea.setText(msgArea.getText() + "\r\n" + "目标文件不能为目录！" +
			// filePath);
			// rightJp.repaint();
		}
		if (!file.getParentFile().exists()) {// 判断目标文件所在的目录是否存在
			// 如果目标文件所在的文件夹不存在，则创建父文件夹
			System.out.println("目标文件所在目录不存在，准备创建它！");
			if (!file.getParentFile().mkdirs()) {// 判断创建目录是否成功
				System.out.println("创建目标文件所在的目录失败！");
				// msgArea.setText(msgArea.getText() + "\r\n" +
				// "创建目标文件所在的目录失败！");
				// rightJp.repaint();
			}
		}
		try {
			if (file.createNewFile()) {// 创建目标文件
				System.out.println("创建文件成功:" + filePath);
				// msgArea.setText(msgArea.getText() + "\r\n" + "创建文件成功:" +
				// filePath);
				// rightJp.repaint();
			} else {
				System.out.println("创建文件失败！" + filePath);
				// msgArea.setText(msgArea.getText() + "\r\n" + "创建文件失败！" +
				// filePath);
				// rightJp.repaint();
			}
		} catch (IOException e) {// 捕获异常
			e.printStackTrace();
			// msgArea.setText(msgArea.getText() + "\r\n" + "创建文件失败！" +
			// e.getMessage());
			// rightJp.repaint();
			System.out.println("创建文件失败！" + e.getMessage());
		}
	}

	private void editServerXml(String path) {
		File file = new File(path);
		if (!file.exists()) {
			throw new GlobleException("server.xml文件不存在！");
		}

		String filename = file.getName();
		// tmpfile为缓存文件，代码运行完毕后此文件将重命名为源文件名字。
		File tmpfile = new File(file.getParentFile().getAbsolutePath()
				+ File.separator + filename + ".tmp");
		BufferedReader reader = null;
		BufferedWriter writer = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					new FileInputStream(file)));
			writer = new BufferedWriter(new FileWriter(tmpfile));
			String huanhang = System.getProperty("line.separator");
			String s = null;
			while ((s = reader.readLine()) != null) {
				s = s.replaceAll(
						"<Server port=\"8100\" shutdown=\"SHUTDOWN\">",
						"<Server port=\"" + new_shutdown_port
								+ "\" shutdown=\"SHUTDOWN\">");
				s = s.replaceAll(
						"<Connector connectionTimeout=\"20000\" port=\"8200\" protocol=\"HTTP/1.1\" redirectPort=\"8443\"/>",
						"<Connector connectionTimeout=\"20000\" port=\""
								+ new_listen_port
								+ "\" protocol=\"HTTP/1.1\" redirectPort=\"8443\"/>");
				writer.write(s + huanhang);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
				if (writer != null) {
					writer.flush();
					writer.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		file.delete();
		tmpfile.renameTo(new File(file.getAbsolutePath()));
	}

	
	private void updateTomcatList(String target_tomcat, String remark) {
		File file = new File(target_tomcat_home + "tomcatList.xml");
		if (!file.exists()) {
			throw new GlobleException("tomcatList.xml文件不存在！");
		}

		SAXReader saxReader = new SAXReader();
		Document doc = null;
		try {
			doc = saxReader.read(target_tomcat_home + "tomcatList.xml");
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		
		Element root = doc.getRootElement();
		Element old = root.element("Record");
		Element Record = (Element)old.clone();
		Record.element("name").setText("tomcat-" + new_listen_port);
		Record.element("path").setText(target_tomcat);
		Record.element("remark").setText(remark);
		Record.element("shutdown_port").setText(new_shutdown_port.toString());
		Record.element("listen_port").setText(new_listen_port.toString());
		
		root.add(Record);
		
		try {  
            /** 将document中的内容写入文件中 */  
			OutputFormat format = OutputFormat.createPrettyPrint();     
            format.setEncoding("UTF-8");     
            FileOutputStream fos = new FileOutputStream(target_tomcat_home + "tomcatList.xml.tmp");   
            XMLWriter writer = new XMLWriter(fos, format);  
            writer.write(doc);  
            writer.close();
        } catch (Exception ex) {  
            ex.printStackTrace();  
        }
		file.delete();
		File tmpfile = new File(target_tomcat_home + "tomcatList.xml.tmp");
		tmpfile.renameTo(new File(file.getAbsolutePath()));
		
	}
	
	private void deleteFile(File webapps) {
		if(webapps.isDirectory()) {
			File[] files = webapps.listFiles();
			for(File file : files) {
				deleteFile(file);
			}
			webapps.delete();
		} else {
			webapps.delete();
		}
	}
}
